//
//  ANSPropertyDescription.m
//  AnalysysAgent
//
//  Created by analysys on 2018/4/9.
//  Copyright © 2018年 analysys. All rights reserved.
//
//  Copyright (c) 2014 Mixpanel. All rights reserved.

#import "ANSPropertyDescription.h"

#pragma mark - ANSPropertySelectorParameterDescription

////**************************** 属性selector参数 ****************************////

@implementation ANSPropertySelectorParameterDescription

- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    NSParameterAssert(dictionary[@"name"] != nil);
    NSParameterAssert(dictionary[@"type"] != nil);
    
    self = [super init];
    if (self) {
        _name = [dictionary[@"name"] copy];
        _type = [dictionary[@"type"] copy];
    }
    
    return self;
}

@end


////**************************** 属性selector ****************************////

#pragma mark - ANSPropertySelectorDescription ***

@implementation ANSPropertySelectorDescription

/** 初始化selector选择器 */
- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    NSParameterAssert(dictionary[@"selector"] != nil);
    NSParameterAssert(dictionary[@"parameters"] != nil);
    
    self = [super init];
    if (self) {
        _selectorName = [dictionary[@"selector"] copy];
        NSMutableArray *parameters = [NSMutableArray arrayWithCapacity:[dictionary[@"parameters"] count]];
        for (NSDictionary *parameter in dictionary[@"parameters"]) {
            [parameters addObject:[[ANSPropertySelectorParameterDescription alloc] initWithDictionary:parameter]];
        }
        
        _parameters = [parameters copy];
        _returnType = [dictionary[@"result"][@"type"] copy]; // optional
    }
    
    return self;
}

@end


////**************************** 属性信息 ****************************////

@interface ANSPropertyDescription ()

@property (nonatomic, readonly) NSPredicate *predicate;

@end


@implementation ANSPropertyDescription

+ (NSValueTransformer *)valueTransformerForType:(NSString *)typeName {
    // TODO: lookup transformer by type
    
    for (NSString *toTypeName in @[@"NSDictionary", @"NSNumber", @"NSString"]) {
        NSString *toTransformerName = [NSString stringWithFormat:@"ANS%@To%@ValueTransformer", typeName, toTypeName];
        NSValueTransformer *toTransformer = [NSValueTransformer valueTransformerForName:toTransformerName];
        if (toTransformer) {
            return toTransformer;
        }
    }
    
    // Default to pass-through.
    return [NSValueTransformer valueTransformerForName:@"ANSPassThroughValueTransformer"];
}

- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    NSParameterAssert(dictionary[@"name"] != nil);
    
    self = [super init];
    if (self) {
        _name = [dictionary[@"name"] copy]; // required
        _useInstanceVariableAccess = [dictionary[@"use_ivar"] boolValue]; // Optional
        _readonly = [dictionary[@"readonly"] boolValue]; // Optional
        _nofollow = [dictionary[@"nofollow"] boolValue]; // Optional
        NSString *predicateFormat = dictionary[@"predicate"]; // Optional  通过过滤器获取属性
        if (predicateFormat) {
            _predicate = [NSPredicate predicateWithFormat:predicateFormat];
        }
        //  通过get方式获取对应属性值
        NSDictionary *get = dictionary[@"get"];
        if (get == nil) {
            NSParameterAssert(dictionary[@"type"] != nil);
            get = @{
                    @"selector": _name,
                    @"result": @{
                            @"type": dictionary[@"type"],
                            @"name": @"value"
                            },
                    @"parameters": @[]
                    };
        }
        //  get selector对象
        _getSelectorDescription = [[ANSPropertySelectorDescription alloc] initWithDictionary:get];
        
        //  可set属性
        NSDictionary *set = dictionary[@"set"];
        if (set == nil && _readonly == NO) {
            NSParameterAssert(dictionary[@"type"] != nil);
            set = @{
                    @"selector": [NSString stringWithFormat:@"set%@:", _name.capitalizedString],
                    @"parameters": @[
                            @{
                                @"name": @"value",
                                @"type": dictionary[@"type"]
                                }
                            ]
                    };
        }
        if (set) {
            _setSelectorDescription = [[ANSPropertySelectorDescription alloc] initWithDictionary:set];
        } else {
            _readonly = YES;
        }
        //  是否可以使用KVC
        BOOL useKVC = (dictionary[@"use_kvc"] == nil ? YES : [dictionary[@"use_kvc"] boolValue]) && _useInstanceVariableAccess == NO;
        
        _useKeyValueCoding = useKVC && _getSelectorDescription.parameters.count == 0 &&
        (_setSelectorDescription == nil || _setSelectorDescription.parameters.count == 1);
    }
    
    return self;
}

- (NSString *)type {
    return _getSelectorDescription.returnType;
}
//  数据类型转换
- (NSValueTransformer *)valueTransformer {
    return [[self class] valueTransformerForType:self.type];
}

- (NSString *)debugDescription {
    return [NSString stringWithFormat:@"<%@:%p name='%@' type='%@' %@>", NSStringFromClass([self class]), (__bridge void *)self, self.name, self.type, self.readonly ? @"readonly" : @""];
}

/** 是否跟踪某个属性 */
- (BOOL)shouldReadPropertyValueForObject:(NSObject *)object {
    if (_nofollow) {
        return NO;
    }
    if (_predicate) {
        return [_predicate evaluateWithObject:object];
    }
    
    return YES;
}



@end



